﻿#include "asynwait.h"
#include <thread>
#include <chrono>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
#ifdef _MSC_VER               // 只有 MSVC
#  if _MSC_VER >= 1900        // VS2015 及以上
#    pragma execution_character_set("utf-8")
#  endif
#endif

AsynWait::AsynWait()
{
}

void AsynWait::start(int precision)
{
    if (mStarted == true)
        return;

    mStarted = true;
    mPrecision = precision;

    thread thd(&AsynWait::run, this);
    mThd.swap(thd);
}

void AsynWait::stop()
{
    mStarted = false;
    mThd.join();
}

void AsynWait::addWaitPack(IdType packetId, AsynWait::OnWaitTimeout onTimeout, int msTimeo)
{
    WaitPack pack;
    pack.id = packetId;
    pack.handler = onTimeout;
    pack.timeo = time_point_cast<milliseconds>(system_clock::now()) + milliseconds(msTimeo);

    mPacksMutex.lock();
    mWaitPacks.push_back(pack);
    mPacksMutex.unlock();
}

void AsynWait::clearWaitPack(IdType packetId)
{
    mPacksMutex.lock();
    mWaitPacks.remove_if([packetId](WaitPack pack) {
        return pack.id = packetId;
    });
    mPacksMutex.unlock();
}

void AsynWait::run()
{
	using namespace std::chrono;
	using std::this_thread::sleep_for;
    list<WaitPack> timeos;
    while (mStarted)
    {
#ifdef WIN32
		sleep_for(milliseconds(mPrecision));   // ← 替换处
#else
        usleep(mPrecision * 1000);
		
#endif
		timeos.clear();

		auto cur = system_clock::now();
        mPacksMutex.lock();
        mWaitPacks.remove_if([&cur, &timeos](const WaitPack &pack) {
            if (cur > pack.timeo)
            {
                timeos.push_back(pack);
                return true;
            }
            return false;
        });
        mPacksMutex.unlock();

        if (!timeos.empty())
        {
            for (auto &pack : timeos)
                pack.handler(pack.id);
        }
    }
}
